home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CYBER.XPO.95
/
CYBER.XPO.95 (Arsenal Computer).ISO
/
popreq
/
amiga1
/
a1000hks.lha
/
TicTac
/
TicTac.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-12
|
14KB
|
531 lines
/*************************************************************************/
/* TicTac.c Betriebsprogramm zum Lesen und Stellen einer */
/* Hardwareuhr am Joystickport#2 am A1000 */
/* c't 1987, Heft 8 */
/* */
/* Funktion: */
/* TicTac Zeit und Datum des Uhrenchips anzeigen */
/* TicTac load Chip lesen und Systemzeit stellen */
/* TicTac save Systemzeit lesen und Chip stellen */
/* */
/* Optimierte Version von A. Peter, 10.01.1992 */
/*************************************************************************/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <exec/libraries.h>
#include <exec/tasks.h>
#include <exec/io.h>
#include <exec/devices.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#define DATRX 0x1000
#define OUTRX 0x2000
#define DATRY 0x4000
#define OUTRY 0x8000
#define OnlyBit7 '\200'
#define AllButBit7 '\177'
#define SELECT WritePotgo(0x2000,SelectMask)
#define DESELECT WritePotgo(0x3000,SelectMask)
#define CLOCKHIGH WritePotgo(0x8000,ClockMask)
#define CLOCKLOW WritePotgo(0xC000,ClockMask)
#define SETDATATOINPUT *myddrao &= AllButBit7
struct TimeAndDate {
int TDhours;
int TDminutes;
int TDseconds;
int TDday_of_week;
int TDdate;
int TDmonth;
int TDyear;
};
struct DosLibrary *DOSBase;
APTR *PotgoBase;
char *myddrao;
char *myprao;
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();
struct TimeAndDate ToBeRead,ToBeWritten;
UWORD allocated,bits;
char firedata;
SelectMask = DATRX | OUTRX;
ClockMask = DATRY | OUTRY;
LONG monthseconds[] = {
0L,0L, 2678400L, 5097600L, 7776000L,
10368000L, 13046400L, 15638400L, 18316800L,
20995200L, 23487200L, 26265600L, 28857600L };
void /* Routinen zum Datenleitung (FIRE) */
DataHigh() /* auf HIGH oder LOW legen */
{
*myddrao |= OnlyBit7;
*myprao |= OnlyBit7;
}
void
DataLow()
{
*myddrao |= OnlyBit7;
*myprao &= AllButBit7;
}
char
IntToBCD(value) /* Umwandlung des Integer-Formats */
int value; /* in fⁿr den Chip verstΣndliches */
{ /* BCD-Format */
return((((value % 100 - value %10)/10)<<4)+ value % 10);
}
int /* Gegenteil von IntToBCD() */
BCDToInt(decimal)
char decimal;
{
return (((decimal >>4)& '\017')*10 + (decimal & '\017'));
}
void /* L÷schen des eigenen TimerPorts */
DeleteTimer(tr)
struct timerequest *tr;
{
struct MsgPort *tp;
tp = tr->tr_node.io_Message.mn_ReplyPort;
if(tp != NULL)
DeletePort(tp);
CloseDevice(tr);
DeleteExtIO(tr,sizeof(struct timerequest));
}
struct timerequest * /* Eigenen TimerPort erstellen */
CreateTimer(unit)
ULONG unit;
{
int error;
struct MsgPort *timerport;
struct timerequest *timermsg;
timerport = CreatePort(0,0);
if(timerport == NULL) return(NULL);
timermsg = (struct timerequest *)
CreateExtIO(timerport,sizeof(struct timerequest));
if(timermsg == NULL) return(NULL);
error = OpenDevice(TIMERNAME,unit,timermsg,0);
if(error != 0) {
DeleteTimer(timermsg);
return(NULL);
}
return(timermsg);
}
int /* Diese Funktion ist fⁿr das Timing */
MicroDelay(MicroSeconds) /* mit dem Chip verantwortlich, sie */
int MicroSeconds; /* wartet ca. 300ms, dann wird der */
{ /* nΣchste Befehl abgearbeitet */
struct timeval currentval;
struct timerequest *tr;
currentval.tv_secs = 0;
currentval.tv_micro = MicroSeconds;
if((tr = CreateTimer(UNIT_MICROHZ)) == NULL)
return(-1);
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time = currentval;
DoIO(tr);
DeleteTimer(tr);
return(0);
}
void /* Diese Funktion gibt einen Takt aus */
outdata()
{
CLOCKHIGH;
MicroDelay(300);
CLOCKLOW;
MicroDelay(300);
}
void
WriteTicTac() /* Stellen von TicTac */
{
register int i,j;
char TicTacTime[8];
TicTacTime[1] = IntToBCD(ToBeWritten.TDhours);
TicTacTime[2] = IntToBCD(ToBeWritten.TDminutes);
TicTacTime[3] = IntToBCD(ToBeWritten.TDdate);
TicTacTime[4] = IntToBCD(ToBeWritten.TDmonth);
TicTacTime[5] = IntToBCD(ToBeWritten.TDyear);
TicTacTime[6] = IntToBCD(ToBeWritten.TDday_of_week);
TicTacTime[7] = IntToBCD(ToBeWritten.TDseconds);
SELECT;
MicroDelay(300);
DataHigh();
for(i=1;i<4;i++)
outdata();
DataLow();
outdata();
for(i=1;i<8;i++)
for(j=0;j<8;j++) {
if(TicTacTime[i] & ('\001' << 7-j))
DataHigh();
else
DataLow();
outdata();
}
DESELECT;
}
int /* Lesen von TicTac */
ReadTicTac()
{
register int i,j;
char TicTacTime[8];
SELECT;
MicroDelay(300);
DataHigh();
for (i=1;i<6;i++)
outdata();
SETDATATOINPUT;
for(i=1;i<8;i++) {
TicTacTime[i] = '\000';
for(j=0;j<8;j++) {
outdata();
firedata = *myprao;
firedata = firedata & OnlyBit7;
firedata = (firedata >> 7-j) & ('\001'<<j);
TicTacTime[i] = TicTacTime[i] | firedata;
}
}
DESELECT;
ToBeRead.TDhours = BCDToInt(TicTacTime[1]);
ToBeRead.TDminutes = BCDToInt(TicTacTime[2]);
ToBeRead.TDdate = BCDToInt(TicTacTime[3]);
ToBeRead.TDmonth = BCDToInt(TicTacTime[4]);
ToBeRead.TDyear = BCDToInt(TicTacTime[5]);
ToBeRead.TDday_of_week=BCDToInt(TicTacTime[6]);
ToBeRead.TDseconds = BCDToInt(TicTacTime[7]);
if(ToBeRead.TDhours == 165 && ToBeRead.TDyear == 165)
return(-1);
return(0);
}
void /* Diese Prozedur wandelt das Systemdatum der */
CalcDate(seconds) /* Amiga in ein "normales" Datum */
LONG seconds;
{
int y,year,i;
year=78;
y=1;
while(y==1)
if (year % 4 == 0 ) /* Schaltjahr */
if (seconds >= 31622400L) {
++year;
seconds -= 31622400L;
}
else
y = 86400;
else /* kein Schaltjahr */
if(seconds >= 31536000L) {
++year;
seconds -= 31536000L;
}
else
y = 0;
ToBeWritten.TDyear = year;
i = 12;
do {
if( i <= 2) y = 0;
if(seconds >= monthseconds[i]+y)
year = -1;
else
--i;
}while(year != -1);
ToBeWritten.TDmonth = i;
seconds -= (monthseconds[i]+y);
ToBeWritten.TDdate = seconds / 86400L + 1;
seconds -= ((ToBeWritten.TDdate-1)*86400L);
ToBeWritten.TDhours = seconds / 3600;
seconds -= ToBeWritten.TDhours * 3600;
ToBeWritten.TDminutes = seconds / 60;
seconds -= ToBeWritten.TDminutes * 60;
ToBeWritten.TDseconds = seconds;
ToBeWritten.TDday_of_week = 0; /* Wochentag wird ignoriert */
}
LONG
CalcSeconds(month,year) /* Umwandlung des Jahres und Monats in */
int month,year; /* Sekunden seit dem 01.01.78 */
{
register int y;
LONG seconds = 0L;
for(y=78;y<year;y++)
if(y%4 == 0 ) /* Schaltjahr */
seconds += 31622400L;
else
seconds += 31536000L;
if ((y%4 == 0) && (month > 2))
seconds += 86400L;
seconds += monthseconds[month];
return(seconds);
}
int /* SetNewTime() stellt die Uhr der Amiga neu */
SetNewTime(secs)
LONG secs;
{
struct timerequest *tr;
if((tr = CreateTimer(UNIT_MICROHZ)) == NULL) return(-1);
tr->tr_node.io_Command = TR_SETSYSTIME;
tr->tr_time.tv_secs = secs;
tr->tr_time.tv_micro = 0;
DoIO(tr);
DeleteTimer(tr);
return(0);
}
int
GetSystemTime(tv) /* GetSystemTime() liest die Uhr der Amiga */
struct timeval *tv;
{
struct timerequest *tr;
if((tr = CreateTimer(UNIT_MICROHZ)) == NULL )return(-1);
tr->tr_node.io_Command = TR_GETSYSTIME;
DoIO(tr);
*tv = tr->tr_time;
DeleteTimer(tr);
return(0);
}
char /* Wird von Ausgabe() zur Konvertierung des TimeAndDate- */
Zehnerrest(a) /* struct in eine Zeichenkette verwendet */
int a;
{
return(a % 10 + '0');
}
void /* Ausgabe() gibt das Datum und die Zeit im deutschen */
Ausgabe() /* Format (mit fⁿhrenden Nullen) aus. */
{
char Zeile[] = "\n\2331;33mE050-C16\2330m: . . , : . Uhr\n";
int z;
z = ToBeRead.TDdate;
Zeile[21] = Zehnerrest(z);
Zeile[20] = Zehnerrest(z/=10);
z = ToBeRead.TDmonth;
Zeile[24] = Zehnerrest(z);
Zeile[23] = Zehnerrest(z/=10);
z = ToBeRead.TDyear+1900;
Zeile[29] = Zehnerrest(z);
Zeile[28] = Zehnerrest(z/=10);
Zeile[27] = Zehnerrest(z/=10);
Zeile[26] = Zehnerrest(z/=10);
z = ToBeRead.TDhours;
Zeile[33] = Zehnerrest(z);
Zeile[32] = Zehnerrest(z/=10);
z = ToBeRead.TDminutes;
Zeile[36] = Zehnerrest(z);
Zeile[35] = Zehnerrest(z/=10);
z = ToBeRead.TDseconds;
Zeile[39] = Zehnerrest(z);
Zeile[38] = Zehnerrest(z/=10);
/* Auf printf() wird verzichtet, da es unn÷tig Speicher fri▀t. */
/* Statt dessen wird die normale DOS-Funktion Write() verwendet. */
/* Auch die restlichen Ausgaben erfolgen mit Write()!. */
Write(Output(),Zeile,45);
}
void
main(argc,argv)
int argc;
char *argv[];
{
struct timeval currentval;
LONG SysSeconds;
int ticErr=0;
myddrao = (char *)0xbfe2ffL;
myprao = (char *)0xbfe0ffL;
if(!(DOSBase = (struct DosLibrary *)
OpenLibrary("dos.library",0L))) exit(30);
if((PotgoBase = (APTR *)OpenResource("potgo.resource")) == NULL)
{
Write(Output(),"\2331;33mE050-C16\2330m: OpenResource 'potgo.resource' failed.\n",57);
ticErr = 26;
goto ErrExit;
}
bits = DATRX | DATRY | OUTRX | OUTRY;
allocated = AllocPotBits(bits);
if(allocated != bits) {
Write(Output(),"\2331;33mE050-C16\2330m: AllocPotBits() failed.\n",42);
ticErr = 21;
goto ErrExit;
}
DESELECT;
CLOCKLOW;
if(argc == 1)
{
if(ReadTicTac() == -1) {
Write(Output(),"\2331;33mE050-C16:\2330m\n",19);
Write(Output(),"TicTac kann Zeit nicht lesen.\n",30);
ticErr = 11;
goto ErrExit;
}
Ausgabe();
}
else if (*argv[1] == 'l' || *argv[1] == 'L') {
if(ReadTicTac() == -1) {
Write(Output(),"\2331;33mE050-C16:\2330m\n",19);
Write(Output(),"TicTac kann Zeit nicht lesen.\n",30);
Write(Output(),"Systemzeit nicht aktualisiert!\n",31);
ticErr = 12;
goto ErrExit;
}
SysSeconds = CalcSeconds(ToBeRead.TDmonth,ToBeRead.TDyear) +
(LONG)ToBeRead.TDseconds +
(LONG)ToBeRead.TDminutes * 60L +
(LONG)ToBeRead.TDhours * 3600L +
(LONG)(ToBeRead.TDdate-1)*86400L;
if(SetNewTime(SysSeconds) == -1) {
Write(Output(),"\2331;33mE050-C16\2330m: SetSystemTime failed.\n",41);
ticErr = 13;
goto ErrExit;
}
Ausgabe();
}
else if (*argv[1] == 's' || *argv[1] == 'S') {
if(GetSystemTime(¤tval) == -1) {
Write(Output(),"\2331;33mE050-C16\2330m: GetSysTime() failed.\n",40);
ticErr = 10;
goto ErrExit;
}
CalcDate(currentval.tv_secs);
WriteTicTac();
Write(Output(),"TicTac gestellt!\n",17);
}
else
Write(Output(),"AUFRUF: TicTac [load][save]\n",28);
ErrExit:
if(ticErr < 30)
SETDATATOINPUT;
if(ticErr < 25)
FreePotBits(allocated);
CloseLibrary(DOSBase);
/****************************************************************/
/* Fehlercodes: */
/* ------------ */
/* 0: TicTac ordentlich beendet, */
/* 10: Systemzeit konnte nicht gelesen werden, */
/* 11: Chip konnte nicht gelen werden (Uhr angeschlossen ?), */
/* 12: dto. beim Versuch Systemzeit nach Chip zu stellen, */
/* 13: Systemzeit konnte nicht verΣndert werden, */
/* 21: AllocPortBits() lieferte Fehler, */
/* 26: 'potgo.resource' konnte nicht ge÷ffnet werden, */
/* 30: DOS konnte nicht ge÷ffnet werden (?!). */
/****************************************************************/
exit(ticErr);
}